package com.rpcservice.rpc.remoting.transport;

import com.rpcservice.rpc.common.extension.SPI;
import com.rpcservice.rpc.remoting.dto.RpcRequest;

/**
 * RPC request transport interface
 * 先定义了一个发送 RPC 请求的顶层接口，然后我们分别使用 Socket 和 Netty 两种方式对这个接口进行实现即可！
 * 这样，我们就可以在不修改任何代码的情况下，替换底层的实现方式。
 * 这就是 SPI 机制的魅力！
 * <p>
 * 为什么要区分 API 和 SPI？
 * <p>
 * API (Application Programming Interface)
 * 给使用者（应用/调用方）用的功能接口。库/框架对外暴露的“可调用能力”。
 * 例：java.sql.Connection#prepareStatement()、Netty 的 Bootstrap、你项目里的 UserService#getById。
 * <p>
 * SPI (Service Provider Interface)
 * 给实现者/扩展方用的扩展接口。框架定义“插槽”，第三方/你自己去提供实现，框架在运行期装配。
 * 例：JDBC 驱动、日志绑定（SLF4J ↔ Logback/Log4j2）、序列化/压缩插件、Spring 的 ApplicationContextInitializer 扩展等。
 * <p>
 * 一句话：API 是“我怎么用你”，SPI 是“我怎么给你插一个实现”。
 *
 * @SPI 是什么？解决什么问题
 * 用在接口上，声明“这是一个扩展点（Service Provider Interface）”，允许在运行期按名字选择不同实现。
 * 配合扩展加载器（如 Dubbo 的 ExtensionLoader）+ 约定的资源文件，做到：
 * 按名字拿实现（getExtension("gzip")）
 * 拿默认实现（@SPI("gzip") → getDefaultExtension()）
 * 运行期自适应选择实现（配合 @Adaptive，根据 URL 参数等路由到具体实现）
 * 条件自动激活（配合 @Activate）
 * 一句话：@SPI = 声明“这个接口支持插件化”，可在不改代码的前提下替换实现。
 */
@SPI
public interface RpcRequestTransport {
    /**
     * send rpc request to server and get result
     *
     * @param request
     * @return
     * @throws Exception
     */
    Object sendRpcRequest(RpcRequest request) throws Exception;
}
